//clause 该类的重点在于为相关子句提供构建方法

package clause

import (
	"fmt"
	"strings"
)

//generator 传入参数,构建出相关的sql语句后返回,如果有参数,会额外返回一个参数数组
type generator func(values ...interface{}) (string, []interface{})

//generators 存放生成各个子句的函数映射表
var generators map[Type]generator

func init() {
	generators = make(map[Type]generator)
	generators[INSERT] = _insert
	generators[VALUES] = _values
	generators[SELECT] = _select
	generators[LIMIT] = _limit
	generators[WHERE] = _where
	generators[ORDERBY] = _orderBy
}

//genBindVars 给构建values子句提供支持
//传入的num表示存在多少个占位符
//最终构建出来的形式如下: ?,?,?
func genBindVars(num int) string {
	var vars []string
	for i := 0; i < num; i++ {
		vars = append(vars, "?")
	}
	return strings.Join(vars, ", ")
}

//_insert 构造insert子句
//例如: insert into user (name,age)
func _insert(values ...interface{}) (string, []interface{}) {
	tableName := values[0]
	fields := strings.Join(values[1].([]string), ",")
	return fmt.Sprintf("INSERT INTO %s (%v)", tableName, fields), []interface{}{}
}

//_values 构造values子句
//例如: values ("dhy",18),("xpy",20)....
func _values(values ...interface{}) (string, []interface{}) {
	// VALUES ($v1), ($v2), ...
	var bindStr string
	var sql strings.Builder
	var vars []interface{}
	sql.WriteString("VALUES ")
	//每一个value就是一个切片数组==> [dhy,18],[xpy,20]
	for i, value := range values {
		//[dhy,18]
		v := value.([]interface{})
		//bindStr= ?,?
		if bindStr == "" {
			bindStr = genBindVars(len(v))
		}
		//Values (?,?) ....
		sql.WriteString(fmt.Sprintf("(%v)", bindStr))
		//说明还有(?,?)需要拼接,因此这里在当前已经拼接好的values子句后面加上一个,
		//Values (?,?),
		if i+1 != len(values) {
			sql.WriteString(", ")
		}
		//vars=[dhy,18]
		vars = append(vars, v...)
	}
	//返回拼接好的values子句和对应的实际参数值
	//values (?,?),(?,?) , [dhy,18,xpy,20]
	return sql.String(), vars
}

//_select 构造select子句
//例如: select name,age from stu
func _select(values ...interface{}) (string, []interface{}) {
	// SELECT $fields FROM $tableName
	tableName := values[0]
	fields := strings.Join(values[1].([]string), ",")
	return fmt.Sprintf("SELECT %v FROM %s", fields, tableName), []interface{}{}
}

//_limit 构造limit子句
func _limit(values ...interface{}) (string, []interface{}) {
	// LIMIT $num
	return "LIMIT ?", values
}

//_where 构造where子句
func _where(values ...interface{}) (string, []interface{}) {
	// WHERE $desc
	desc, vars := values[0], values[1:]
	return fmt.Sprintf("WHERE %s = ?", desc), vars
}

//_orderBy 构造orderBy子句
func _orderBy(values ...interface{}) (string, []interface{}) {
	return fmt.Sprintf("ORDER BY %s", values[0]), []interface{}{}
}
